﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using ObligatorioBD.MerObjects;

namespace ObligatorioBD.Logic
{
    class MERInterpreter
    {
        XmlDocument doc;
        Mer mer;
        public MERInterpreter(string xml)
        {
            doc = new XmlDocument();
            doc.LoadXml(xml);
        }
        public void Interpret()
        {
            XmlNode root = doc.FirstChild;
            XmlNode nodo = root.SelectSingleNode("Info");
            ParseMerInfo(nodo);
            nodo = root.SelectSingleNode("Entities");
            ParseEntities(nodo);
            nodo = root.SelectSingleNode("Relations");
            ParseRelations(nodo);
            //string a = "break";
        }
        public void PersistMer()
        {
            MerPersistor p = new MerPersistor();
            p.PersistMer(this.mer);
        }

        #region Parser Methods
        private void ParseMerInfo(XmlNode merNode)
        {
            string name = merNode.SelectSingleNode("Name").InnerText;
            string owner = "";
            if (merNode.SelectSingleNode("Owner") != null)
            {
                owner = merNode.SelectSingleNode("Owner").InnerText;
            }
            this.mer = new Mer(name, owner);
        }
        private void ParseEntities(XmlNode entitiesNode)
        {
            if (entitiesNode.ChildNodes.Count != 0)
            {
                XmlNode entityNode = entitiesNode.FirstChild;
                mer.AddEntity(ParseEntity(entityNode));
                entitiesNode.RemoveChild(entityNode);
                ParseEntities(entitiesNode);
            }
        }
        private Entity ParseEntity(XmlNode entityNode)
        {
            string entityType = "S";
            if (entityNode.Attributes["Type"] != null)
            {
                entityType = entityNode.Attributes["Type"].Value;
            }
            Entity e = new Entity(entityNode.Attributes["Name"].Value, ParseEntityType(entityType));
            ParseAtributes(entityNode.SelectSingleNode("Atributes"), e);
            return e;
        }
        private bool ParseEntityType(string type)
        {
            return (type.ToUpper() == "W");
        }
        private void ParseRelations(XmlNode relationsNode)
        {
            if (relationsNode.ChildNodes.Count != 0)
            {
                XmlNode relationNode = relationsNode.FirstChild;
                mer.AddRelation(ParseRelation(relationNode));
                relationsNode.RemoveChild(relationNode);
                ParseRelations(relationsNode);
            }
        }
        private Relationship ParseRelation(XmlNode relationNode)
        {
            Relationship r = new Relationship(relationNode.Attributes["Name"].Value);
            ParseAtributes(relationNode.SelectSingleNode("Atributes"), r);
            ParseRelationEntities(relationNode.SelectSingleNode("Entities"), r);
            return r;
        }
        private void ParseRelationEntities(XmlNode entities, Relationship r)
        {
            if (entities != null && entities.ChildNodes.Count != 0)
            {
                XmlNode entity = entities.FirstChild;
                Entity e = this.mer.GetEntityByName(entity.Attributes["Name"].Value);
                string cardinality = entity.Attributes["Cardinality"].Value;
                r.AddEntity(e, cardinality);
                entities.RemoveChild(entity);
                ParseRelationEntities(entities, r);
            }
        }
        private void ParseAtributes(XmlNode node, IAtributeObject obj)
        {
            if (node != null && node.ChildNodes.Count != 0)
            {
                XmlNode atributeNode = node.FirstChild;
                obj.AddAtribute(ParseAtribute(atributeNode));
                node.RemoveChild(atributeNode);
                ParseAtributes(node, obj);
            }
        }
        private Atribute ParseAtribute(XmlNode atributeNode)
        {
            bool isPrimary = Convert.ToBoolean(atributeNode.Attributes["Key"].Value);
            string name = atributeNode.Attributes["Name"].Value;
            string type = atributeNode.Attributes["Type"].Value;
            int quantity = 1;
            if (atributeNode.Attributes["Cantidad"] != null)
            {
                quantity = Convert.ToInt32(atributeNode.Attributes["Cantidad"].Value);
                //a.Cantidad = Convert.ToInt32(atributeNode.Attributes["Cantidad"].Value);
            }
            Atribute a = new Atribute(name, Atribute.GetType(type), quantity,isPrimary);
            if (a.Type == Atribute.AtributeType.CompositeType)
            {
                ParseAtributes(atributeNode.SelectSingleNode("Atributes"), a);
            }
            
            return a;
        }
        #endregion
    }
}
